package com.genreate.util.zos;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.HttpMethod;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import com.amazonaws.services.securitytoken.AWSSecurityTokenService;
import com.amazonaws.services.securitytoken.AWSSecurityTokenServiceClientBuilder;
import com.amazonaws.services.securitytoken.model.AssumeRoleRequest;
import com.amazonaws.services.securitytoken.model.AssumeRoleResult;
import com.amazonaws.services.securitytoken.model.Credentials;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.time.Instant;
import java.util.Date;
import java.util.Map;

public class ZosUtil {
    public static String ACCESS_KEY = "QO45HX3AKSFX5EBWXLW6";
    public static String SECRET_KEY = "NIz3YaYARq9Z49Zt5pfSuPM0Y0rXsCvt7xCBXLn7";
    public static String END_POINT = "xinan1.zos.ctyun.cn";
    public static String BUCKET = "bucket-shineray-dev-app";
    public static String STS_ROLE_NAME = "arn:aws:iam:::role/role-5b72";

    public static AWSSecurityTokenService stsClient =
            AWSSecurityTokenServiceClientBuilder.standard()
                    .withEndpointConfiguration(new
                            AwsClientBuilder.EndpointConfiguration(END_POINT, ""))
                    .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)))
                    .build();

    public static void main(String[] args) throws Exception {
//        ZosUtil zosUtil = new ZosUtil();
//        Credentials sts_app_session = zosUtil.assumeRole("sts_app_session");
        getPolicy("2025/07/23/"+IdUtil.fastSimpleUUID()+".jpg");
//        System.out.println("2025/07/23/"+IdUtil.fastSimpleUUID()+".jpg");
    }

    /**
     * 获取表单域
     *
     * @param key 钥匙
     * @return {@link Map }<{@link String }, {@link String }>
     * @throws Exception 例外
     */
    public static Map<String, String> getPolicy(String key) throws Exception {
        PostObjectSDK sdk = new PostObjectSDK(ACCESS_KEY, SECRET_KEY, END_POINT);

        PostObjectSDK.PostObjectPolicy policy = new PostObjectSDK.PostObjectPolicy();
        policy.setExpiration(900);
        policy.addEqualCondition("acl", "public-read");

        PostObjectSDK.PostObjectRequest request = sdk.generatePostObjectRequest(BUCKET, key, null, policy);
        request.addFormFields("acl", "public-read");

        Map<String, String> formFields = request.getFormFields();
        formFields.forEach((k,v)->{
            System.out.println(k + ":" + v);});
        return request.getFormFields();
    }

    public static void test(String key) throws IOException{
        //获取预签名Url
        GeneratePresignedUrlRequest var = new
                GeneratePresignedUrlRequest(BUCKET, key);
        Date expiration = new Date();
        long expTimeMillis = Instant.now().toEpochMilli();
        expTimeMillis += 1000 * 60 * 60;
        // 设置有效期60分钟
        expiration.setTime(expTimeMillis);
        var.setExpiration(expiration);
        var.setMethod(HttpMethod.PUT);
        URL url = getS3Client().generatePresignedUrl(var);
        //创建上传链接并上传对象
        System.out.println(key);
        System.out.print(url.toString() + "\n");
        System.out.print(getZosUrl(key) + "\n");
    }

    public static void test2(String key) throws IOException {
        AmazonS3 s3Client = getS3Client();

        Date expiration = new Date();
        long expTimeMills = expiration.getTime();
        expTimeMills += 1000 * 60 * 60;
        expiration.setTime(expTimeMills);
        GeneratePresignedUrlRequest generatePresignedUrlRequest =
                new GeneratePresignedUrlRequest(BUCKET, key)
                        .withMethod(HttpMethod.PUT)
                        .withExpiration(expiration);
        URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
        System.out.println(url.toString());
        //创建HTTP连接并上传对象
        HttpURLConnection connection = (HttpURLConnection)
                url.openConnection();
        connection.setDoOutput(true);
        connection.setRequestMethod("PUT");
        connection.setRequestProperty("x-amz-acl", "public-read");
        FileInputStream in = new FileInputStream("C:\\Users\\ljhdy\\Pictures\\test.jpg");
        OutputStream out = connection.getOutputStream();

        // 改进的文件读取循环，确保完整上传文件
        byte[] buffer = new byte[8192]; // 使用更合理的缓冲区大小
        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
        }
        // 获取HTTP响应状态
        int responseCode = connection.getResponseCode();
        System.out.println(getZosUrl(key));
    }

    /**
     * 存在文件
     *
     * @param zosPath zos路径
     * @return boolean
     */
    public static boolean existFile(String zosPath) {
        GetObjectMetadataRequest var = new
                GetObjectMetadataRequest(BUCKET,zosPath);
        try {
            getS3Client().getObjectMetadata(var);
            return true;
        }catch (Exception e) {
            return false;
        }
    }

    /**
     * 下载文件
     *
     * @param zosPath       zos路径
     * @param localFilePath 本地文件路径
     */
    public static void downloadFile(String zosPath, String localFilePath) {
        try {
            GetObjectRequest request = new GetObjectRequest(BUCKET, zosPath);
            S3Object result = getS3Client().getObject(request);
            // 保存到本地
            try {
                InputStream in = result.getObjectContent();
                File outputFile = new File(localFilePath);
                FileOutputStream outputStream = new
                        FileOutputStream(outputFile);
                byte[] read_buf = new byte[1024 * 1024];
                int read_len = 0;
                while ((read_len = in.read(read_buf)) > 0) {
                    outputStream.write(read_buf, 0, read_len);
                }
                in.close();
                outputStream.close();
            } catch (IOException e){
                e.printStackTrace();
            }
        }catch (Exception e) {
            System.out.print("=====request fail=====\n");
            System.out.print(e.getMessage());
        }
    }

    /**
     * 获取s3客户端
     *
     * @return {@link AmazonS3 }
     */
    public static AmazonS3 getS3Client() {
        AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY)))
                .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(END_POINT, ""))
                .disableChunkedEncoding()
                .enablePathStyleAccess()
                .build();
        return s3Client;
    }

    /**
     * 上传
     *
     * @param file 文件
     * @return {@link String }
     */
    public String upload(File file) {
        String zosPath = getZosPath(file.getName());
        AmazonS3 s3Client = getS3Client();
        try {
            PutObjectRequest request = new PutObjectRequest(BUCKET, zosPath, file);
            setPublicRead(request);
            s3Client.putObject(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return getZosUrl(zosPath);
    }

    /**
     * 上传
     *
     * @param multipartFile 多部分文件
     * @return {@link String }
     */
    public String upload(MultipartFile multipartFile) {
        String zosPath = getZosPath(multipartFile.getOriginalFilename());
        AmazonS3 s3Client = getS3Client();
        ;
        try {
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(multipartFile.getContentType());
            metadata.setContentLength(multipartFile.getSize());

            PutObjectRequest request = new PutObjectRequest(BUCKET, zosPath, multipartFile.getInputStream(), metadata);
            setPublicRead(request);

            s3Client.putObject(request);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return getZosUrl(zosPath);
    }

    /**
     * 设置公共读取
     *
     * @param request 请求
     */
    public static void setPublicRead(PutObjectRequest request) {
        CannedAccessControlList cannedAcl = CannedAccessControlList.PublicRead;
        request.setCannedAcl(cannedAcl);
    }

    /**
     * 获取zos路径
     *
     * @param fileName 文件名包含后缀
     * @return {@link String }
     */
    public static String getZosPath(String fileName) {
        String ymd = DateUtil.format(new Date(), "yyyy/MM/dd");
        String zosPath = StrUtil.format("{}/{}.{}", ymd,
                IdUtil.simpleUUID(), FileNameUtil.extName(fileName));
        return zosPath;
    }

    /**
     * 获取zos url
     *
     * @param zosUrl zos url
     * @return {@link String }
     */
    public static String getZosUrl(String zosUrl) {
        return StrUtil.format("https://{}.{}/{}", BUCKET, END_POINT, zosUrl);
    }

    /**
     * 删除
     *
     * @param filepath 文件路径
     * @return {@link String }
     */
    public static String delete(String filepath) {
        try {
            DeleteObjectRequest request = new DeleteObjectRequest(BUCKET, filepath);
            getS3Client().deleteObject(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "删除成功";
    }

    /**
     * 承担角色
     *
     * @param sessionName 会话名称
     */
    public Credentials assumeRole(String sessionName) {
        AssumeRoleRequest request = new AssumeRoleRequest();
        request.setRoleArn(STS_ROLE_NAME);
        request.setRoleSessionName(sessionName);
        AssumeRoleResult result = stsClient.assumeRole(request);
        return result.getCredentials();
    }
}